/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.ove.openmath.jome.formaters.om;

/**
 *
 * @author Mr.Sam
 */
import java.util.*;
import fr.ove.utils.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.formaters.om.OpenMathFormaterResoucesManager;

import java.awt.*;
import java.awt.event.*;
import fr.ove.openmath.jome.ctrl.linear.*;

/**
* Formats the formula tree structure as its corresponding OpenMath object.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 07/01/2000
*/
public class OpenMathFormater extends FormaterRepository {
    /**
    * The resources manager of the formater
    */
    OpenMathFormaterResoucesManager resourcesManager = new OpenMathFormaterResoucesManager("fr.ove.openmath.jome.formaters.om.OpenMathFormaterResources");
    
    /**
    * The repository of formaters
    */
    private Hashtable repository = new Hashtable();
    
    /**
    * Returns the formater with the specified identifier.
    * @param objectId the object (to format) identifier.
    */
    public Formater getFormater(String objectId) {
        String formaterName = resourcesManager.getFormater(objectId);
        formaterName = (formaterName == null) ? resourcesManager.getFormater("defaultFormater") : formaterName;
        
        Formater formater = (Formater) repository.get(formaterName);
        if (formater == null) {
            formater = (Formater) Factory.getClassInstance(formaterName);
            repository.put(formaterName, formater);
        }
        
        return formater;
    }
    
    /**
    * Returns the specified object formatted as a string.
    * @param formatedObject the formatted object (for structured object, could represents the beginning).
    * @param repository where the different other formaters are.
    * @param obj the object to format.
    */
    public String format(String formatedObject, FormaterRepository formaterRepository, Object obj) {
        String objectId = ((FormulaTreeStructure) obj).getResourceIdentifier();
        Formater formater = getFormater(objectId);
        return formater.format(formatedObject, formaterRepository, obj); // En fait, le formatage à proprement parlé commence là
    }
    
    /**
    * Returns the cd name of the specified property.
    * @param objectId the object (to format) identifier.
    */
    public String getCdName(String objectId) {
        return resourcesManager.getCdName(objectId);        
    }
    
    /**
    * Returns the symbol name of the specified property.
    * @param objectId the object (to format) identifier.
    */
    public String getSymbolName(String objectId) {
        return resourcesManager.getSymbolName(objectId);        
    }
    
    /**
    * Returns the OpenMath object of the specified formula tree structure.
    * @param fts the specified formula tree structure.
    */
    public String getOpenMath(FormulaTreeStructure fts) {
        return format("", this, fts);
    }
    
    /*
    * Methods to write OpenMath
    */
    
    /**
    * Writes the OpenMath start object tag.
    * @return the <OMOBJ> tag.
    */
    public String writeStartObject() {
        incIndent();
        return "<OMOBJ>\n";
    }
    
    /**
    * Writes the OpenMath end object tag.
    * @return the </OMOBJ> tag.
    */
    public String writeEndObject() {
        decIndent();
        return "</OMOBJ>\n";
    }
    
    /**
    * Writes the OpenMath start application tag.
    * @return the <OMA> tag.
    */
    public String writeStartApplication() {
        String indent = getIndent();
        incIndent();
        return indent + "<OMA>\n";
    }
    
    /**
    * Writes the OpenMath end application tag.
    * @return the </OMA> tag.
    */
    public String writeEndApplication() {
        decIndent();
        return getIndent() + "</OMA>\n";
    }
    
    /**
    * Writes the OpenMath start error tag.
    * @return the <OMe> tag.
    */
    public String writeStartError() {
        String indent = getIndent();
        incIndent();
        return indent + "<OME>\n";
    }
    
    /**
    * Writes the OpenMath end error tag.
    * @return the </OME> tag.
    */
    public String writeEndError() {
        decIndent();
        return getIndent() + "</OME>\n";
    }
    
    /**
    * Writes the OpenMath start binding tag.
    * @return the <OMBIND> tag.
    */
    public String writeStartBinding() {
        String indent = getIndent();
        incIndent();
        return indent + "<OMBIND>\n";
    }
    
    /**
    * Writes the OpenMath end binding tag.
    * @return the </OMBIND> tag.
    */
    public String writeEndBinding() {
        decIndent();
        return getIndent() + "</OMBIND>\n";
    }
    
    /**
    * Writes the OpenMath start bound variables tag.
    * @return the <OMBVAR> tag.
    */
    public String writeStartBoundVariables() {
        String indent = getIndent();
        incIndent();
        return indent + "<OMBVAR>\n";
    }
    
    /**
    * Writes the OpenMath end bound variables tag.
    * @return the </OMBVAR> tag.
    */
    public String writeEndBoundVariables() {
        decIndent();
        return getIndent() + "</OMBVAR>\n";
    }
    
    /**
    * Writes the OpenMath start attribution tag.
    * @return the <OMATP> tag.
    */
    public String writeStartAttribution() {
        String indent = getIndent();
        incIndent();
        return indent + "<OMATP>\n";
    }
    
    /**
    * Writes the OpenMath end attribution tag.
    * @return the </OMATP> tag.
    */
    public String writeEndAttribution() {
        decIndent();
        return getIndent() + "</OMATP>\n";
    }
    
    /**
    * Writes the OpenMath start attribute pair tag.
    * @return the <OMATTR> tag.
    */
    public String writeStartAttributePair() {
        String indent = getIndent();
        incIndent();
        return getIndent() + "<OMATTR>\n";
    }
    
    /**
    * Writes the OpenMath end attribute pair tag.
    * @return the </OMATTR> tag.
    */
    public String writeEndAttributePair() {
        decIndent();
        return getIndent() + "</OMATTR>\n";
    }
    
    /**
    * Writes a float (decimal format, not hexa).
    * @param value the float value.
    */
    public String writeFloat(String value) {
        return getIndent() + "<OMF dec = \"" + value + "\"/>\n";
    }
    
    /**
    * Writes an integer (decimal format, not hexa)
    * @param value the integer value.
    */
    public String writeInteger(String value) {
        return getIndent() + "<OMI>" + value + "</OMI>\n";
    }
    
    /**
    * Writes a variable.
    * @param value the variable value.
    */
    public String writeVariable(String value) {
        return getIndent() + "<OMV name=\""+ value +"\"/>\n";
    }
    
    /**
    * Writes the symbol with the specified identifier.
    * @param objectId the identifier of the symbol to write.
    */
    public String writeSymbol(String objectId) {
        return getIndent() + "<OMS cd=\""+getCdName(objectId)+"\" name=\""+getSymbolName(objectId)+"\"/>\n";
    }
    
    /**
    * Writes the specified symbol.
    * @param cdName the name of the symbol CD.
    * @param symbName thename of the symbol.
    */
    public String writeSymbol(String cdName, String symbName) {
        return getIndent() + "<OMS cd=\""+cdName+"\" name=\""+symbName+"\"/>\n";
    }
    
    /**
    * Test.
    */
    public static void main(String args[]) {
        Frame f = new Frame();
        f.setLayout(new BorderLayout());
        
        TextArea ta = new TextArea();
        f.add(ta, "Center");
        
        TextField tf = new TextField();
        tf.addActionListener(new TfAdapter(ta));
        f.add(tf, "South");
        
        f.pack();
        f.setSize(f.getPreferredSize());
        f.setVisible(true);
    }
}
    
    class TfAdapter implements ActionListener {
        Formula f = new Formula();
        LinearParser lp;
        TextArea ta;
        OpenMathFormater omf = new OpenMathFormater();
        
        public TfAdapter(TextArea ta) {
            this.ta = ta;
            lp = new LinearParser();
            lp.addLinearParserListener(f);
        }
        
        public void actionPerformed(ActionEvent e) {
            TextField src = (TextField) e.getSource();
            lp.parse(src.getText());
            
            System.out.println(f.getLinear());
            
            ta.setText(omf.getOpenMath(f));
        }
    }
